package com.xbongbong.paas.toolbox.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public final class ReflectUtil {
	private static final Logger LOG = LoggerFactory.getLogger(ReflectUtil.class);

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List<Class> getSonClass(Class fatherClass) {
		List<Class> sonClassList = new ArrayList<Class>();
		String packageName = fatherClass.getPackage().getName();
		LOG.warn(packageName);
		List<Class> packageClassList = getPackageClass(packageName);
		for (Class clazz : packageClassList) {
			if (fatherClass.isAssignableFrom(clazz) && !fatherClass.equals(clazz)) {
				sonClassList.add(clazz);
			}
		}
		return sonClassList;
	}

	@SuppressWarnings({ "rawtypes" })
	private static List<Class> getPackageClass(String packageName) {
		ClassLoader loader = ReflectUtil.class.getClassLoader();
		String path = packageName.replace(".", "/");
		LOG.warn(path);
		Enumeration<URL> resources = null;
		try {
			resources = loader.getResources(path);
		} catch (IOException e) {
			e.printStackTrace();
		}
		List<File> fileList = new ArrayList<File>();
		LOG.warn(resources.toString());
		while (resources.hasMoreElements()) {
			URL resource = resources.nextElement();
			fileList.add(new File(resource.getFile()));
		}
		ArrayList<Class> classList = new ArrayList<Class>();
		for (File file : fileList) {
			classList.addAll(findClass(file, packageName));
		}
		LOG.warn(classList.toString());
		return classList;
	}

	@SuppressWarnings({ "rawtypes" })
	private static List<Class> findClass(File file, String packageName) {
		List<Class> classList = new ArrayList<Class>();
		if (!file.exists()) {
			return classList;
		}
		File[] fileArray = file.listFiles();
		for (File subFile : fileArray) {
			if (subFile.isDirectory()) {
				assert !file.getName().contains(".");
				classList.addAll(findClass(subFile, packageName + "." + subFile.getName()));
			} else if (subFile.getName().endsWith(".class")) {
				try {
					classList.add(Class.forName(packageName + "." + subFile.getName().split(".class")[0]));
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
		LOG.warn(classList.toString());
		return classList;
	}
}
